import useAppStore from '@/store/modules/app';
import Tools from '@/utils/tools';
import useLoading from '../hooks/useLoading';
import { IMOU_APPID, IMOU_APPSECRET } from '@/config/app';
import md5 from 'js-md5';

type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';

interface RequestOptions {
  url: string;
  method?: HttpMethod;
  data?: any;
  headers?: Record<string, string>;
  timeout?: number;
}

interface HttpResponse<T = any> {
  statusCode: number;
  data: {
    id: string;
    result: HttpResponseData<T>;
  };
  errMsg: string;
  headers: Record<string, string>;
}

interface HttpResponseData<T> {
  msg: string;
  code: string;
  data: T;
}

export interface RequestParams {
  [key: string]: any;
  hasLoading?: boolean;
}
const { showLoading, hideLoading } = useLoading();
class Http {
  private readonly baseURL: string;
  private defaultOptions: Partial<RequestOptions> = {
    method: 'GET',
    timeout: 6000,
    headers: {
      'Content-Type': 'application/json',
    },
  };

  constructor(baseURL: string = 'https://openapi.lechange.cn/openapi/') {
    this.baseURL = baseURL;
  }

  // 请求拦截器
  private requestInterceptor: ((options: RequestOptions) => RequestOptions) | null = null;

  // 生成指定数量的随机数
  private makeRandom(number: number): string {
    const chars = [
      '0',
      '1',
      '2',
      '3',
      '4',
      '5',
      '6',
      '7',
      '8',
      '9',
      'A',
      'B',
      'C',
      'D',
      'E',
      'F',
      'G',
      'H',
      'I',
      'J',
      'K',
      'L',
      'M',
      'N',
      'O',
      'P',
      'Q',
      'R',
      'S',
      'T',
      'U',
      'V',
      'W',
      'X',
      'Y',
      'Z',
      'a',
      'b',
      'c',
      'd',
      'e',
      'f',
      'g',
      'h',
      'i',
      'j',
      'k',
      'l',
      'm',
      'n',
      'o',
      'p',
      'q',
      'r',
      's',
      't',
      'u',
      'v',
      'w',
      'x',
      'y',
      'z',
    ];
    let nums = '';
    for (var i = 0; i < number; i++) {
      var id = parseInt(Math.random() * 61);
      nums += chars[id];
    }
    return nums;
  }

  // 设置请求拦截器
  setRequestInterceptor(interceptor: (options: RequestOptions) => RequestOptions) {
    this.requestInterceptor = interceptor;
  }

  request<T>(options: RequestOptions): Promise<HttpResponseData<T>> {
    if (options.method === 'GET') {
      const params = Tools.parseUrlParams(options.url);
      if (params['hasLoading']) showLoading();
    } else {
      if (options.data && options.data.hasLoading) showLoading();
    }
    // 合并默认配置与传入的请求配置
    const finalOptions: RequestOptions = {
      ...this.defaultOptions,
      ...options,
      url: this.baseURL + options.url,
      headers: { ...this.defaultOptions.headers, ...options.headers },
    };

    // 执行请求拦截器
    if (this.requestInterceptor) {
      Object.assign(finalOptions, this.requestInterceptor(finalOptions));
    }
    const time = parseInt(Date.now() / 1000);
    const nonce = this.makeRandom(32);
    const sign = `time:${time},nonce:${nonce},appSecret:${IMOU_APPSECRET}`;

    return new Promise((resolve, reject) => {
      uni.request({
        url: finalOptions.url,
        method: finalOptions.method || 'GET',
        data: {
          params: { ...finalOptions.data, token: options.url !== 'accessToken' && !finalOptions.data.token ? useAppStore().$state.IMOU_TOKEN : '' },
          system: {
            ver: '1.0',
            appId: IMOU_APPID,
            sign: md5(sign),
            nonce,
            time,
          },
          id: nonce,
        },
        header: finalOptions.headers,
        timeout: finalOptions.timeout,
        success: async (res: any) => {
          const response: HttpResponse<T> = {
            statusCode: res.statusCode,
            data: res.data,
            headers: res.header || {},
            errMsg: res.errMsg,
          };

          if (!response.data || response.statusCode !== 200) {
            await uni.showModal({ icon: 'error', showCancel: false, content: '服务器错误，请重试' });
            return reject(response.errMsg);
          }

          if (response.data.result.code === '0') {
            return resolve(response.data.result);
          } else {
            useAppStore().$patch({ IMOU_TOKEN: '' });
            await uni.showModal({ icon: 'error', showCancel: false, content: response.data.result.msg });
            return reject(response.data.result.msg);
          }
        },
        fail: (err) => {
          reject(err);
        },
        complete: () => {
          hideLoading();
        },
      });
    });
  }

  // GET 请求
  get<T>(url: string, params?: Record<string, any>, headers?: Record<string, string>): Promise<HttpResponseData<T>> {
    const query = params
      ? '?' +
        Object.entries(params)
          .map(([key, val]) => `${encodeURIComponent(key)}=${encodeURIComponent(val)}`)
          .join('&')
      : '';
    return this.request({ url: url + query, method: 'GET', headers });
  }

  // POST 请求
  post<T>(url: string, data?: any, headers?: Record<string, string>): Promise<HttpResponseData<T>> {
    return this.request({ url, method: 'POST', data, headers });
  }

  // PUT 请求
  put<T>(url: string, data?: any, headers?: Record<string, string>): Promise<HttpResponseData<T>> {
    return this.request({ url, method: 'PUT', data, headers });
  }

  // DELETE 请求
  delete<T>(url: string, data?: any, headers?: Record<string, string>): Promise<HttpResponseData<T>> {
    return this.request({ url, method: 'DELETE', data, headers });
  }
}

// 创建一个 Http 实例
const http_imou = new Http();

// 请求拦截器
http_imou.setRequestInterceptor((options) => {
  // 添加通用的 Authorization 请求头
  options.headers = {
    ...options.headers,
  };
  return options;
});

export default http_imou;
